#include "pos.h"
#include "systick.h"
#include "RTClock.h"
#include "pos_param.h"
#include "pos_timer.h"
#include "oper.h"
#include "rfid_rc522.h"
#include "display.h"
#include <string.h>
#include "XRCORE.h"
#include "reader_cpu.h"
#include "reader.h"
#include "beep.h"
#include "gd32e230c_bsp.h"
#include "uSPI.h"

#ifdef DUAL_MODE
#define OUT_1    1
#define OUT_2    2
#define KEY_ON  0
#define KEY_0FF 1
#endif

TPos Pos;
//static uint8_t times; //??????????????????????
uint8_t G_DualRatModeShow;
#ifdef DUAL_MODE
uint8_t G_key1_flag, G_key2_flag;
#endif
uint8_t G_CardSN[4] = {0, 0, 0, 0};
#ifdef DUAL_MODE
uint8_t GNumBlocktem[16];
#endif

extern uint8_t G_Error_Count;

uint16_t (*While_CardOn)(void);




void CPU_M1_While_CardOn()
{
    if(GCPUCard)
    {   While_CardOn = CmdReadCPURand; }
    else
    {   While_CardOn = CheckM1Card; }
}

static void Return_PcdReset(void)
{
    InitSPI();
    PcdReset();
    PcdAntennaOff();
    delay_ms (2);
    PcdAntennaOn();
}

static uint8_t DoDayLimit(void)
{
    //???? ? ?????????
    //static uint8_t oBlock[16];
    if(PosParam.DayLimitFlag == 1)
    {
        if ((c.Day == Reader.Purse.Date) && (Reader.Purse.DayLimitAmo >= PosParam.DayLimit)) // ??????? ?? ??
        {
            Valve_OFF;
            SetPulseCounter(off);
            SetTime13_Counter(off);
            SetTime14_Counter(off); 
            SaveAmountFun();
            //CPU_M1_While_CardOn();
            while (Reader.ReadMoney() == nil)
            {
                disp.Clear();
                delay_ms(300);
                disp.Balance(Reader.Purse.Balance);
            #ifdef SEGLCD
                disp.Symbols(LimitFullYuan);
            #endif
                Beep.BeepGap(3);
                delay_ms(300);
            }
            return 1;
        }
    }

    return 0;  
}

//????????
static void DelayCutProcess(void)
{
    uint8_t oSec = 0;

    if(PosParam.ChargeDelay && Reader.Purse.Balance > 0){
        disp.Clear();
        SetTime14_Counter(on);
        CPU_M1_While_CardOn();
        while (Time14_Count < PosParam.ChargeDelay){
            oSec = PosParam.ChargeDelay - Time14_Count; //??????????
        #ifdef SEGLCD
            disp.Symbols(StopLine);
            disp.WriteMulDig(6, 2, oSec);
        #elif defined DIGLED
            disp.OneNum(6, 0, '-');
            disp.OneNum(7, 1, oSec/10%10);
            disp.OneNum(8, 1, oSec%10);
	    #endif
        
            if (While_CardOn() != nil){   
                break; 
            }
        }
        SetTime14_Counter(off);
        //disp.Clear();
        disp.Balance(Reader.Purse.Balance);  //????
    }
}

void DoUsingOnF7(void)
{
    static uint16_t err;
    uint8_t GNumBlock1[16];
    uint8_t sele = 0;

    err = Reader.PrepaySmall(PosParam.RationModeFee*10, true); //?????BUF????*10
    if (err != nil){
        Valve_OFF;

        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn() == nil);

        disp.Complete();
        return;
    }

#ifdef SEGLCD
    disp.segDash(6);
    disp.Symbols(ModeTime);   //??
    disp.LcdData(18, 0x00); 
    disp.Symbols(okLine);     //ok
#elif defined DIGLED
    disp.OneNum(1, 0, 'D');
    disp.OneNum(2, 0, ' ');
#endif
    
    SetTime13_Counter(on);
    SetTime14_Counter(on);

    Valve_ON;//???????IO?
    if(PosParam.RationInCrad == 1){
        //CPU_M1_While_CardOn();
        while ((Time14_Count < PosParam.RationModeTime) && (Reader.ReadMoney() == nil)){
            disp.DisTiming(PosParam.RationModeTime - Time14_Count);
            if ((Time13_Count2 / 100) >= 3 ){ 
                Time13_Count2 = 0;
            #ifdef SEGLCD    
                switch (sele) {
                    case 0:  disp.LcdData(15, 0x01);
                                disp.LcdData(16, 0x00); sele ++; break;
                    case 1:  disp.LcdData(15, 0x02); sele ++; break;
                    case 2:  disp.LcdData(15, 0x04); sele ++; break;
                    case 3:  disp.LcdData(15, 0x00);
                                disp.LcdData(16, 0x08); sele ++; break;
                    case 4:  disp.LcdData(16, 0x04); sele ++; break;
                    case 5:  disp.LcdData(16, 0x01); sele =0; break;
                    default: break;
                }
            #elif defined DIGLED
                switch (sele) {
                    case 0:  disp.OneNum(8, 2, 0x01); sele ++; break;
                    case 1:  disp.OneNum(8, 2, 0x02); sele ++; break;
                    case 2:  disp.OneNum(8, 2, 0x04); sele ++; break;
                    case 3:  disp.OneNum(8, 2, 0x08); sele ++; break;
                    case 4:  disp.OneNum(8, 2, 0x10); sele ++; break;
                    case 5:  disp.OneNum(8, 2, 0x20); sele =0; break;
                    default: break;
                }
            #endif
            }
        }
    }else{
        while (Time14_Count < PosParam.RationModeTime){
        #ifdef SYS_FWDGT
            static uint32_t oNextTick;  
            if(SysTickAfter(oNextTick)){
                fwdgt_counter_reload();
                SetDueTickMS(&oNextTick, 3000);
            }
        #endif
            disp.DisTiming(PosParam.RationModeTime - Time14_Count);
            if ((Time13_Count2 / 100) >= 3 ) { 
                Time13_Count2 = 0;
            #ifdef SEGLCD    
                switch (sele) {
                    case 0:  disp.LcdData(15, 0x01);
                                disp.LcdData(16, 0x00); sele ++; break;
                    case 1:  disp.LcdData(15, 0x02); sele ++; break;
                    case 2:  disp.LcdData(15, 0x04); sele ++; break;
                    case 3:  disp.LcdData(15, 0x00);
                                disp.LcdData(16, 0x08); sele ++; break;
                    case 4:  disp.LcdData(16, 0x04); sele ++; break;
                    case 5:  disp.LcdData(16, 0x01); sele =0; break;
                    default: break;
                }
            #elif defined DIGLED
                if (sele >= 5) {   
                    disp.OneNum(8, 2, 0x20); 
                    sele = 0; 
                }else{
                    disp.OneNum(8, 2, 0x01 << sele); 
                    sele++;
                }
            #endif
            }
        }
    }

    Valve_OFF;                       
    SetTime14_Counter(off);   
    SetTime13_Counter(off);    

#ifdef SEGLCD
    disp.segDash(1); disp.segDash(2);disp.segDash(3);disp.segDash(4);disp.segDash(5);
#elif defined DIGLED
    disp.segDash(2); disp.segDash(3);disp.segDash(4);disp.segDash(5);disp.segDash(6);
#endif
    Beep.BeepTime(500);

    CheckCardOn();
}

// ????????? 24
uint8_t SpecDeduModeTime(void)//????????????
{
    static uint16_t err;
    static uint32_t  oCounted, oCounted1;
    static uint32_t  oSec;
    uint8_t GNumBlock1[16];
    uint8_t sele = 0;
	volatile static uint32_t *oTimeCount; 
	
    oSec = PosParam.SpecDeduPulse;

    err = Reader.PrepaySmall(PosParam.SpecDeduFee, true);//???
    if (err != nil) { //??????? 
        Valve_OFF;

        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn() == nil);

        disp.Complete();
        return 2;
    }

    disp.Balance(Reader.Purse.Balance);
#ifdef SEGLCD
    disp.Symbols(ModeTimeYuan); // ?? + ?
    disp.Symbols(MoneyExclama);
    disp.Symbols(NumLine);
#elif defined DIGLED
    disp.OneNum(1, 2, 0x4C);
#endif

    if(PosParam.MeasureMode == 0x10) {   
        oCounted = Model_Time_Base;
        oTimeCount = &Time13_Count; 
        SetTime13_Counter(on);// ?????
    } else if(PosParam.MeasureMode == 0x30) {   
        oCounted = 1;
        oTimeCount = &Time14_Count;
        SetTime14_Counter(on);
    }

    Valve_ON;//???????IO?
    if(PosParam.SpecDeduInCrad == 1) {
        //CPU_M1_While_CardOn();
        while ((oSec) && (Reader.ReadMoney() == nil)) {
        #ifdef DIGLED
            disp.OneNum(7, 0, '-');
        #endif
            if (oSec <= PosParam.SpecDeduPulse) {
            #ifdef SEGLCD    
                disp.OneNum(6, 0, (oSec / 10) % 10);   
                if ((Time13_Count/80%10) < 5)       //?????
                {   disp.OneNum(7, 1, oSec % 10); }
                else
                {   disp.OneNum(7, 0, oSec % 10); }
            #elif defined DIGLED
                if ((Time13_Count2 / 50) >= 5) {
                    Time13_Count2 = 0;
                    if (sele >= 5) {   
                        disp.OneNum(8, 2, 0x20); 
                        sele = 0; 
                    }else{
                        disp.OneNum(8, 2, 0x01 << sele); 
                        sele++;
                    }
                }
            #endif
            }

            if(*oTimeCount < oCounted) {   continue; }
        #ifdef DIGLED
            disp.OneNum(7, 1, '-');
        #endif
            if(PosParam.MeasureMode == 0x10){
               oCounted = oCounted + Model_Time_Base;//?????????    
            }else if (PosParam.MeasureMode == 0x30){
               oCounted = oCounted + 1; 
            }
            oSec--;
        }
        
        Valve_OFF;//?????
        if(PosParam.MeasureMode == 0x10) {   
            SetTime13_Counter(off);
        } else if(PosParam.MeasureMode == 0x30) {   
            SetTime14_Counter(off);
        }
        SetPulseCounter(off);

        Beep.BeepTwinkle();
        delay_ms(500);
        Beep.BeepGap(2);
        disp.Complete();
        delay_ms(500);
    } else {
        while (oSec){   
        #ifdef SYS_FWDGT
            static uint32_t oNextTick;  
            if(SysTickAfter(oNextTick)){
                fwdgt_counter_reload();
                SetDueTickMS(&oNextTick, 3000);
            }
        #endif
        #ifdef DIGLED
            disp.OneNum(7, 0, '-');
        #endif
            if (oSec <= PosParam.SpecDeduPulse) {
			#ifdef SEGLCD    
				disp.OneNum(6, 0, (oSec / 10) % 10);   
				if ((Time13_Count/80%10) < 5)       //?????
				{   disp.OneNum(7, 1, oSec % 10); }
				else
				{   disp.OneNum(7, 0, oSec % 10); }
			#elif defined DIGLED
                if ((Time13_Count2 / 50) >= 5) {
                    Time13_Count2 = 0;
                    if (sele >= 5) {   
                        disp.OneNum(8, 2, 0x20); 
                        sele = 0; 
                    }else{
                        disp.OneNum(8, 2, 0x01 << sele); 
                        sele++;
                    }
                }
            #endif
            }

			if(*oTimeCount < oCounted) {   continue; }
			#ifdef DIGLED
				disp.OneNum(7, 1, '-');
			#endif

            if(PosParam.MeasureMode == 0x10){
                oCounted = oCounted + Model_Time_Base;//?????????    
            }else if (PosParam.MeasureMode == 0x30){ 
                oCounted = oCounted + 1; 
            }

            oSec--;
        }
        //disp.OneNum ( 7, 0, oSec % 10 );//????? ???????????0

        Valve_OFF;//?????
        if(PosParam.MeasureMode == 0x10) {   
            SetTime13_Counter(off);
        } else if(PosParam.MeasureMode == 0x30) {   
            SetTime14_Counter(off);
        }
        SetPulseCounter(off);

        Beep.BeepTwinkle();
        delay_ms(500);
        Beep.BeepGap(2);
        disp.Complete();
        delay_ms(500);
    }
    return 0;
}

uint8_t SpecDeduModePlus(void)
{
    static uint16_t err;
    static uint32_t oCounted;
    uint8_t GNumBlock1[16];
    uint8_t sele = 0;

    err = Reader.PrepaySmall(PosParam.SpecDeduFee, true);
    if (err != nil) {
        Valve_OFF;
        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn() == nil){}

        disp.Complete();
        return 2;
    }

    disp.Balance(Reader.Purse.Balance);
#ifdef SEGLCD
    disp.Symbols(ModePulseYuan);
    disp.Symbols(MoneyExclama);
    disp.Symbols(NumLine);
#elif defined DIGLED
    disp.OneNum(1, 2, 0x4c);
#endif
    if(PosParam.MeasureMode == 0x20){
        oCounted = PosParam.SpecDeduPulse * 16; 
    }else if(PosParam.MeasureMode == 0x60){
        oCounted = PosParam.SpecDeduPulse; 
    }
    SetTime13_Counter(on);
    SetTime14_Counter(on);
    SetPulseCounter(on);
    PulseTimeOut = 0;

    Valve_ON;//???????IO?
    if(PosParam.SpecDeduInCrad == 1){
        //CPU_M1_While_CardOn();
        while ((G_PulseCount < oCounted) && (Reader.ReadMoney() == nil)){
            if(PosParam.StopSec){
                if(Time14_Count > PosParam.StopSec){  //????+????????????
                    if (PulseTimeOut < 5) { 
                        Valve_OFF;
                        SetTime13_Counter(off); //?????????
                        SetPulseCounter(off);
                        SetTime14_Counter(off);
                        while (Reader.ReadMoney() == nil){
                            disp.TimeOut(); 
                        }
                        return 2;
                    }else {
                        PulseTimeOut = 0;
                        Time14_Count = 0;
                    }
                }
            }
        #ifdef SEGLCD   
            disp.WriteMulDig(6, 2, PulseCounted%100);  //PulseCounted1???????
        #elif defined DIGLED
            if (G_PulseCount2 >= 8) {
                G_PulseCount2 = 0;
                if (sele >= 5) {   
                    disp.OneNum(8, 2, 0x20); 
                    sele = 0; 
                }else{
                    disp.OneNum(8, 2, 0x01 << sele); 
                    sele++;
                }
                if(sele == 0){   
                    disp.OneNum(7, 1, '_'); 
                }else{   
                    disp.OneNum(7, 0, '_'); 
                }
            }
        #endif
        }

        Valve_OFF;  
        PulseTimeOut = 0;
        SetTime13_Counter(off);
        SetPulseCounter(off);   
        SetTime14_Counter(off);

        Beep.BeepTwinkle();
        delay_ms(500);
        Beep.BeepGap(2);
        disp.Complete();
        delay_ms(500);
    } else {
        while (G_PulseCount < oCounted) {
        #ifdef SYS_FWDGT
            static uint32_t oNextTick;  
            if(SysTickAfter(oNextTick)){
                fwdgt_counter_reload();
                SetDueTickMS(&oNextTick, 3000);
            }
        #endif
            if(PosParam.StopSec) {
                if(Time14_Count > PosParam.StopSec){        //????+????????????
                    if(PulseTimeOut < 5) {   
                        Valve_OFF;
                        SetPulseCounter(off);
                        SetTime13_Counter(off);             //?????????
                        SetTime14_Counter(off);
                        //CPU_M1_While_CardOn();
                        while (Reader.ReadMoney() == nil){
                            disp.TimeOut(); 
                        }
                        G_PulseCount = oCounted + 1;
                        return 2;
                    }else{   
                        PulseTimeOut = 0;
                        Time14_Count = 0;
                    }
                }
            }
        #ifdef SEGLCD   
            disp.WriteMulDig(6, 2, PulseCounted%100);  //PulseCounted1???????
        #elif defined DIGLED
            if (G_PulseCount2 >= 8) {
                G_PulseCount2 = 0;
                if (sele >= 5) {   
                    disp.OneNum(8, 2, 0x20); 
                    sele = 0; 
                }else{
                    disp.OneNum(8, 2, 0x01 << sele); 
                    sele++;
                }
                if(sele == 0){
                    disp.OneNum(7, 1, '_'); 
                }else{
                    disp.OneNum(7, 0, '_'); 
                }
            }
        #endif
        }

        Valve_OFF;//?????
        PulseTimeOut = 0;
        SetPulseCounter(off);
        SetTime13_Counter(off);
        SetTime14_Counter(off);

        Beep.BeepTwinkle();
        delay_ms(500);
        Beep.BeepGap(2);
        disp.Complete();
        delay_ms(500);
    }
    return 0;
}

//????????
void DoUsingOnTime()
{
    static uint16_t err;
    static uint32_t oCounted;
    static uint32_t oSec;
    static uint32_t oSecC;
    uint8_t sele = 0;
    uint8_t cardOnFlag = 0;
    volatile uint32_t *oTimeCount;
    int increment = 0;       

    oSecC = PosParam.OutPulse;  
    oSec = 0;

    err = Reader.PrepaySmall(PosParam.OutFee, true);    // ???
    if (err != nil){
        Valve_OFF;
        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn() == nil){}

		disp.Complete();
        return;
    }

    disp.Balance(Reader.Purse.Balance);
#ifdef SEGLCD
    disp.Symbols(ModeTimeYuan);         // ?? + ?
    disp.Symbols(NumLine);
    disp.Symbols(SMoney);
#elif defined DIGLED
    disp.OneNum(1, 0, '-');
#endif 

    if (PosParam.MeasureMode == 0x10){
        oCounted = Model_Time_Base;
        oTimeCount = &Time13_Count;
        SetTime13_Counter(on);          // ?????
    }else if (PosParam.MeasureMode == 0x30){
        oCounted = 1; 
        oTimeCount = &Time14_Count;
        SetTime14_Counter(on);
    }
    //SetPulseCounter(on);

    Valve_ON;  //???????IO?
    //CPU_M1_While_CardOn();
    while (Reader.ReadMoney() == nil) {     //??????
        err = DoDayLimit();    // ???
        if(err != nil) {   
            break;
        }
    #ifdef DIGLED
        disp.OneNum(7, 0, '-');
    #endif
        if (*oTimeCount < oCounted) {
        #ifdef SEGLCD
            disp.OneNum(6, 0, ((oSec % 100) / 10) % 10);
            if ((Time13_Count / 10) % 10 < 5)
            {   disp.OneNum(7, 1, (oSec % 100) % 10); } 
            else
            {   disp.OneNum(7, 0, (oSec % 100) % 10); }
        #elif defined DIGLED
            if (Time13_Count2 >= 100) {   
                Time13_Count2 = 0;
                if (sele >= 5) {   
                    disp.OneNum(8, 2, 0x20); 
                    sele = 0; 
                }else{
                    disp.OneNum(8, 2, 0x01 << sele); 
                    sele++;
                }
            }
        #endif
            continue;
        }
        if (*oTimeCount >= 0x7FFFFFCD) {
            *oTimeCount = 0;
            oCounted = 0;
        }
    #ifdef DIGLED
        disp.OneNum(7, 1, '-');
    #endif
        if(PosParam.MeasureMode == 0x10){
            oCounted = oCounted + Model_Time_Base;//?????????    
        }else if (PosParam.MeasureMode == 0x30){
            oCounted = oCounted + 1; 
        }
        oSec++;
        if (oSec < oSecC){ 
            continue; 
        }

        err = Reader.PrepaySmall(PosParam.OutFee, false);
        if (err != nil) {
            Valve_OFF;//?????
            Beep.BeepGap(3);
            CPU_M1_While_CardOn();
            while (While_CardOn() == nil) {}
            break;
        }
        disp.Balance(Reader.Purse.Balance);
        oSecC = PosParam.OutPulse;
        oSec = 0;
    }
    Valve_OFF;//?????
    SetPulseCounter(off);
    SetTime13_Counter(off); // ?????????
    SetTime14_Counter(off);
    SaveAmountFun();
    disp.Complete();
}

//??????????????????
void DoUsingOnPulse()
{
    static uint16_t err;
    static uint32_t oCounted;
    uint8_t sele = 0;

    oCounted = (uint32_t)(PosParam.OutPulse * PosParam.PosMult16);
    err = Reader.PrepaySmall(PosParam.OutFee, true);
    if (err != nil) {
        Valve_OFF;//?????
        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn() == nil);

        disp.Complete();
        return;
    }

    disp.Balance(Reader.Purse.Balance);
#ifdef SEGLCD
    disp.Symbols(ModePulseYuan);
    disp.Symbols(NumLine);
    disp.Symbols(SMoney);
    disp.WriteMulDig(6, 2, 0);
#elif defined DIGLED
    disp.OneNum(1, 0, '-');
#endif
    SetPulseCounter(on);
    //SetTime13_Counter(on);
    SetTime14_Counter(on);
    Valve_ON;
    //CPU_M1_While_CardOn();
    while (Reader.ReadMoney() == nil){
        err = DoDayLimit();
        if (err != nil) {
            return;
        } 
    #ifdef DIGLED
        disp.OneNum(7, 0, '_');
    #endif
        if (PosParam.StopSec){
            if (Time14_Count > PosParam.StopSec) {   //????+????????????
                if (PulseTimeOut < 5) {
                    Valve_OFF;
                    SetPulseCounter(off);
                    SetTime13_Counter(off);
                    SetTime14_Counter(off);
                    while (Reader.ReadMoney() == nil){   
                        disp.TimeOut(); 
                    }
                    break;
                }else{
                    PulseTimeOut = 0;
                    Time14_Count = 0;
                }
            }
        }
    #ifdef SEGLCD
        if (PulseCounted < (uint32_t)(PosParam.OutPulse * PosParam.PosMult16)){ 
            disp.WriteMulDig(6, 2, PulseCounted%100);       //PulseCounted1???????
        }
    #elif defined DIGLED
        if (G_PulseCount2 >= 8) {
            G_PulseCount2 = 0;
            if (sele >= 5) {   
                disp.OneNum(8, 2, 0x20); 
                sele = 0; 
            }else{
                disp.OneNum(8, 2, 0x01 << sele); 
                sele++;
            }
        }
    #endif
        if (PosParam.LiterDisplay == 1){
            if (Time14_Count2 % 4 <= 1){
            #ifdef SEGLCD
                disp.LcdData(12, 0x01);//??
            #elif defined DIGLED
                disp.OneNum(1, 0, '-');
            #endif
                disp.Balance(Reader.Purse.Balance);
            }else{
                disp.Liter(G_PulseCount);
            #ifdef SEGLCD
                disp.LcdData(12, 0x08 + 0x01); //??+?
            #elif defined DIGLED
                disp.OneNum(1, 0, 'L');
            #endif
            }
        }else{
        #ifdef SEGLCD
            disp.LcdData(12, 0x01);//??
        #endif
            disp.Balance(Reader.Purse.Balance);
        }

        if (G_PulseCount < oCounted){
            continue;
        }
    #ifdef DIGLED
        disp.OneNum(7, 1, '_');
    #endif
        oCounted = oCounted + (uint32_t)(PosParam.OutPulse * PosParam.PosMult16);       //??????????
        if (oCounted >= 0xFFFFF00F) {  //??????
            oCounted = 0;
        }
    #ifdef SEGLCD
        PulseCounted = 0;
    #endif

        err = Reader.PrepaySmall(PosParam.OutFee, false);
        if (err != nil){
            Valve_OFF;//?????
            Beep.BeepGap(3);
            CPU_M1_While_CardOn();
            while(While_CardOn() == nil){}
            break;
        }
        // Reader.ReadMoney();
    }
    Valve_OFF;
    SetPulseCounter(off);
    SetTime14_Counter(off);
    //SetTime13_Counter(off);
    SaveAmountFun();
    disp.Complete();
}

//??????????
void FreeUsageOnTime()
{
    static uint16_t err;
    static uint32_t  oCounted;
    static uint32_t  oSec, oSecC;

    volatile static uint32_t *oTimeCount; 

    oSec = 0;
    oSecC = PosParam.FreeUsePluse;

    Reader.ReadMoney();
    err = Reader.FreePaySmall(PosParam.FreeUseFee, true);//???
    if(err != nil){
        Valve_OFF;
        disp.ErrorCode(err);
        return;
    }
    if (PosParam.FreeUseMonFlag){ 
        disp.WriteMulDig(1, 5, Reader.Purse.MonthUsage);
    }else{    
        disp.WriteMulDig(3, 3, Reader.Purse.DateUsage);
    }
    delay_ms(300);
    if (PosParam.FreeUseMonFlag){    
        disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage); 
    }else{    
        disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage); 
    }
#ifdef SEGLCD
    disp.LcdData(18, 0x00);//????
    disp.LcdData(11, 0x04 + 0x01); //????+??
    disp.Symbols(Litre); //???
    disp.Symbols(NumLine);
#elif defined DIGLED
    disp.OneNum(6, 0, 'F');
#endif
    
    if(PosParam.MeasureMode == 0x10){
        oCounted = Model_Time_Base;
        oTimeCount = &Time13_Count;
        SetTime13_Counter(on);
    }else if (PosParam.MeasureMode == 0x30){ 
        oCounted = 1; 
        oTimeCount = &Time14_Count;
        SetTime14_Counter(on);
    }
    SetPulseCounter(on);

    Valve_ON;//???????IO?
    //CPU_M1_While_CardOn();
    while (Reader.ReadMoney() == nil){
        //Reader.ReadMoney();

        if (*oTimeCount < oCounted){
        #ifdef SEGLCD
            disp.OneNum(6, 0, ((oSec % 100) / 10) % 10);
            if ((Time13_Count / 10) % 10 < 5){
                disp.OneNum(7, 1, (oSec % 100) % 10); //1???????????
            }else{   
                disp.OneNum(7, 0, (oSec % 100) % 10); 
            }
        #elif defined DIGLED
            disp.OneNum(7, 0, ((oSec % 100) / 10) % 10);
            if ((Time13_Count / 10) % 10 < 5){
                disp.OneNum(8, 1, (oSec % 100) % 10);//1???????????
            }else{   
                disp.OneNum(8, 0, (oSec % 100) % 10); 
            }
        #endif
            continue;
        }

        if(PosParam.MeasureMode == 0x10){
            oCounted = oCounted + Model_Time_Base;
        }else if (PosParam.MeasureMode == 0x30){ //?????????     
            oCounted = oCounted + 1; 
        }

        oSec++;
        if (oSec < oSecC){   continue; }

        err = Reader.FreePaySmall(PosParam.FreeUseFee, false);
        if (err != nil){
            if (PosParam.FreeUseMonFlag){
                disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage);
            }else{    
                disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage);
            }
            Valve_OFF;
            break;
        }

        if(PosParam.FreeUseMonFlag){
            if ((PosParam.FreeUseTotal - Reader.Purse.MonthUsage) <= PosParam.FreeRemWarn){    
                Beep.BeepOnce();
            }
            disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage);
        }else{
            if ((PosParam.FreeUseTotal - Reader.Purse.DateUsage) <= PosParam.FreeRemWarn){    
                Beep.BeepOnce();
            }
            disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage);
        }    

        oSecC = PosParam.FreeUsePluse;
        oSec = 0;
    }
    
    Valve_OFF;
    SetPulseCounter(off);
    SetTime13_Counter(off);
    SetTime14_Counter(off);
}

void FreeUsageOnPlus()
{
    static uint16_t err;
    static uint32_t oCounted;

    oCounted = (uint32_t)PosParam.FreeUsePluse  * PosParam.PosMult16;

    Reader.ReadMoney();
    err = Reader.FreePaySmall(PosParam.FreeUseFee, true);//???;
    if (err != nil){
        Valve_OFF;
        return;
    }
    if (PosParam.FreeUseMonFlag){   
        disp.WriteMulDig(1, 5, Reader.Purse.MonthUsage);
    }else{    
        disp.WriteMulDig(3, 3, Reader.Purse.DateUsage);
    }
    delay_ms(300);
    if (PosParam.FreeUseMonFlag){
        disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage);
    }else{
        disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage);
    }
    
#ifdef SEGLCD
    disp.LcdData(18, 0x00);//????
    disp.LcdData(11, 0x04);//????
    disp.LcdData(12, 0x08 + 0x01); //??+?
    disp.Symbols(NumLine);
#elif defined DIGLED
    disp.OneNum(6, 1, 'F');
#endif

    SetTime13_Counter(on);
    SetTime14_Counter(on);
    SetPulseCounter(on);
    PulseTimeOut = 0;

    Valve_ON;
    //CPU_M1_While_CardOn();
    while (Reader.ReadMoney() == nil){
        //Reader.ReadMoney();
        if (PosParam.StopSec){
            if (Time14_Count > PosParam.StopSec) {      //????+????????????
                if (PulseTimeOut < 5){   
                    Valve_OFF;
                    SetTime13_Counter(off);      //?????????
                    SetPulseCounter(off);
                    SetTime14_Counter(off);
                    while (Reader.ReadMoney() == nil)
                    {   disp.TimeOut(); }
                    break;
                }else{   
                    PulseTimeOut = 0;
                    Time14_Count = 0;
                }
            }
        }

        if (PulseCounted < (uint32_t)PosParam.FreeUsePluse * PosParam.PosMult16){ 
        #ifdef SEGLCD   
            disp.WriteMulDig(6, 2, PulseCounted%100);  //PulseCounted1???????
        #elif defined DIGLED
            disp.WriteMulDig(7, 2, PulseCounted%100);
        #endif
        }
            
        if (G_PulseCount < oCounted){   
            continue; 
        }

        oCounted = oCounted + (uint32_t)PosParam.FreeUsePluse * PosParam.PosMult16; //??????????
        if (oCounted >= 0xFFFFF00F){   
            oCounted = 0; 
        }
        PulseCounted = 0;

        err = Reader.FreePaySmall(PosParam.FreeUseFee, false);
        if (err != nil){
            if (PosParam.FreeUseMonFlag){    
                disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage); 
            }else{    
                disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage); 
            }   

            Valve_OFF;
            break;
        }  
        //????
        if(PosParam.FreeUseMonFlag){
            if (PosParam.FreeUseTotal - Reader.Purse.MonthUsage <= PosParam.FreeRemWarn) {
                Beep.BeepOnce();
            }
            disp.WriteMulDig(1, 5, PosParam.FreeUseTotal - Reader.Purse.MonthUsage);
        }else{
            if (PosParam.FreeUseTotal - Reader.Purse.DateUsage <= PosParam.FreeRemWarn) {
                Beep.BeepOnce();
            }
            disp.WriteMulDig(3, 3, PosParam.FreeUseTotal - Reader.Purse.DateUsage);
        }
    }

    Valve_OFF;
    SetPulseCounter(off);
    SetTime14_Counter(off);
}

//?????? ??????
static void DoFreeUseMode()
{
//    static uint8_t oBlock[16];
//    uint8_t err;
    if (PosParam.FreeUseMode == 1) {// ????????
    
        GetClock();
        disp.Clear();
        if(c.Year <= 10){
            return; 
        }
        if (PosParam.FreeUseMonFlag == 1){
            if (c.Month == Reader.Purse.Month && (Reader.Purse.MonthUsage >= PosParam.FreeUseTotal)) 
            {   return; }
        }else { //????
            if (c.Day == Reader.Purse.Date && (Reader.Purse.DateUsage >= PosParam.FreeUseTotal))
            {   return;}
        }
        if ((PosParam.MeasureMode == 0x20) || (PosParam.MeasureMode == 0x60) || (PosParam.MeasureMode == 0x00)) {       //????
            FreeUsageOnPlus(); 
        }
        if ((PosParam.MeasureMode == 0x10) || (PosParam.MeasureMode == 0x30)){      //????
            FreeUsageOnTime(); 
        }
        delay_ms(300);
    }
}

#ifdef DUAL_MODE
//FD?? ????
void keyRelease()
{
    uint32 oNextTick = 0;

    SetDueTickMS(&oNextTick, 2000);
    while (KEY1 == KEY_ON || KEY2 == KEY_ON) {
        if (SysTickAfter(oNextTick)){
            return;
        }
    }
}
//FD??????
void DualRatMode_Show()
{
    static uint8_t key2_disp,key1_disp;
    static uint8_t DualData_Array[16];
    static uint8_t DualData_Array2[16];
    static uint16_t rSec1,rSec2;
    static uint8_t i,k,m;
    
    if(Time14_Count >= (PosParam.Dual_1RationModeTime * DualRatMode.IncrVal)){
        DualRatMode.IncrVal = 0;
        G_key1_flag = 0 ; 
        Valve_OFF; 
    }
    if(Time14_Count2 >= (PosParam.Dual_2RationModeTime * DualRatMode.IncrVal2)){
        DualRatMode.IncrVal2 = 0;
        G_key2_flag = 0 ; 
        Valve2_OFF; 
    }
    if (G_key1_flag == 0 && G_key2_flag == 0){
        Timer14_Run (0);
        Timer13_Run (0);
        Valve_OFF; 
        Valve2_OFF;
        G_DualRatModeShow = 0;
    }
    if(!GCardOn) {  //??? ??????
        if(G_key1_flag == 1 && G_key2_flag == 1) {  //???????? ????
            rSec1 = (PosParam.Dual_1RationModeTime * DualRatMode.IncrVal)-Time14_Count;      //1?????
            rSec2 = (PosParam.Dual_2RationModeTime * DualRatMode.IncrVal2)-Time14_Count2;     //2?????

            DualData_Array[0] = '1'; DualData_Array[1] = '_'; 
            DualData_Array[4] = '-';

            if((rSec1/60) <= 99) {      //??????
                DualData_Array[2] = rSec1/60/10;
                DualData_Array[3] = rSec1/60%10;
                DualData_Array[5] = rSec1%60/10;
                DualData_Array[6] = rSec1%60%10;
            }else {                      //?????
                DualData_Array[2] = rSec1/60/60/10%10;
                DualData_Array[3] = rSec1/60/60%10;
                DualData_Array[5] = rSec1/60/10%10;
                DualData_Array[6] = rSec1/60%10;
            }
            DualData_Array[7] = ' ';

            DualData_Array[8] = '2'; DualData_Array[9] = '_'; 
            DualData_Array[12] = '-';

            if((rSec2/60) <= 99) {
                DualData_Array[10] = rSec2/60/10;
                DualData_Array[11] = rSec2/60%10;
                DualData_Array[13] = rSec2%60/10;
                DualData_Array[14] = rSec2%60%10;
            }else {
                DualData_Array[10] = rSec2/60/60/10%10;
                DualData_Array[11] = rSec2/60/60%10;
                DualData_Array[13] = rSec2/60/10%10;
                DualData_Array[14] = rSec2/60%10;
            }
            DualData_Array[15] = ' ';
            

            if(Time13_Count >= 3000)  {            //??1?3?
                if( k > 8) {   
                    // ?0123456789ABCDEF ?? 89ABCDEF01234567
                    for(i=0; i<8; i++){   
                        DualData_Array2[i] = DualData_Array[i+8];
                    }
                    for(i=0; i<8; i++){    
                        DualData_Array2[i+8] = DualData_Array[i];
                    }

                    if((Time13_Count-4000) >= 3000)  {       //??2?3?
                        if(Time13_Count2 >= 100)   {   //????
                            Time13_Count2 = 0;
                            for(i=0; i<8 ; i++) {
                                disp.OneNum(i+1,0,DualData_Array2[i+m]);  //2?�>1?????
                            }
                            m++;
                            if(m>8) {   
                                m=0;
                                k=0;
                                Time13_Count = 0;
                            }
                        }
                    }else {
                        for(i=0; i<8 ; i++)  {
                            disp.OneNum(i+1,0,DualData_Array2[i]);
                        }
                    }
                }else {          //??2?3?
                    if(Time13_Count2 >= 100)  {   //????
                        Time13_Count2 = 0;
                        for(i=0; i<8 ; i++) {
                            disp.OneNum(i+1,0,DualData_Array[i+k]);  //1?->2?????
                        }
                        k++;
                    }
                }
            }else  {       //??1?3?
                for(i=0; i<8 ; i++) {
                    disp.OneNum(i+1,0,DualData_Array[i]);
                }
            }
        }else if (G_key1_flag == 1 )  {      //?1???
            Time13_Count2 = 0;
            disp.OneNum(1,0,1);
            disp.OneNum(2,0,'_');
            disp.DisTiming((PosParam.Dual_1RationModeTime * DualRatMode.IncrVal)-Time14_Count);
            disp.OneNum(8, 0, ' ');
        }else if (G_key2_flag == 1 )  {      //?2???
            Time13_Count2 = 0;
            disp.OneNum(1,0,2);
            disp.OneNum(2,0,'_');
            disp.DisTiming((PosParam.Dual_2RationModeTime * DualRatMode.IncrVal2)-Time14_Count2);
            disp.OneNum(8, 0, ' ');
        }
    }else if (G_key1_flag == 1 || G_key2_flag == 1) {
        disp.OneNum(1,0,'-');
    }
}

void DualRatMode_Run()
{
    static uint16_t err = 0;

    disp.Clear();
    if ((PosParam.MaxBalance_Flag == 1) && (Reader.Purse.Balance > PosParam.MaxBalance)) {//???????
        //???? ??????
        Beep.BeepGap(1);
        disp.ErrorCode(406);//?????????
        if(G_DualRatModeShow == 1)
        {   return; }
        CheckCardOn();
        return;
    }
    if ((Reader.Purse.Balance < PosParam.RetenMoney) && PosParam.RetenMoneyFlag){//?????????
        //???? ?????
        Beep.BeepGap(1);
        disp.ErrorCode(407);//?????????
        if(G_DualRatModeShow == 1)
        {   return; }
        CheckCardOn();
        return;
    }

    disp.Balance(Reader.Purse.Balance);  //????
    G_DualRatModeShow = 1;
    if (KEY1 == KEY_ON || KEY2 == KEY_ON)  {
//        uint32_t KeyTime_Count = get_systick_ms();
        SetTime13_Counter (on);// ?????
        delay_ms(50); 

        if(KEY1 == RESET) {   
            if(!G_key1_flag){
                err = Reader.PrepaySmall(PosParam.Dual_1RationModeFee, true);
                if ( err != nil ) {
                    Valve_OFF;//?????
                    disp.ErrorCode(err);
                    return ;
                }
                G_key1_flag = 1 ;
                DualRatMode.IncrVal = 1;
                Time14_Count = 0;
                Valve_ON;

                keyRelease();

            }else{
                if(DualRatMode.Incr){  
                    if (DualRatMode.IncrVal >= 99){
                        disp.ShowString("  -99-  ");
                        Beep.BeepGap(3);
                        return ;
                    }
                    err = Reader.PrepaySmall(PosParam.Dual_1RationModeFee, true);
                    if ( err != nil ) {
                        disp.ErrorCode(err);
                        return ;
                    }

                    DualRatMode.IncrVal++;
                    Beep.BeepOnce();
                    disp.Clear();
                    disp.OneNum(4, 0, (DualRatMode.IncrVal)/10);
                    disp.OneNum(5, 0, (DualRatMode.IncrVal)%10);
                    delay_ms(200); 

                    keyRelease();

                    return ;
                }else{
                    return ;
                }
            }
        } else if(KEY2 == RESET) {   
            if(!G_key2_flag){
                err = Reader.PrepaySmall(PosParam.Dual_2RationModeFee, true);
                if ( err != nil ) { 
                    Valve2_OFF;//?????
                    disp.ErrorCode(err);
                    return ;
                }
                G_key2_flag = 1 ;
                Time14_Count2 = 0;
                DualRatMode.IncrVal2 = 1;
                Valve2_ON; 

                keyRelease();

            }else{
                if(DualRatMode.Incr){  
                    if (DualRatMode.IncrVal2 >= 99){
                        disp.ShowString("  -99-  ");
                        Beep.BeepGap(3);
                        return ;
                    }
                    err = Reader.PrepaySmall(PosParam.Dual_2RationModeFee, true);
                    if ( err != nil ) {
                        disp.ErrorCode(err);
                        return ;
                    }

                    DualRatMode.IncrVal2++;
                    Beep.BeepOnce();
                    disp.Clear();
                    disp.OneNum(4, 0, (DualRatMode.IncrVal2)/10);
                    disp.OneNum(5, 0, (DualRatMode.IncrVal2)%10);
                    delay_ms(200); 

                    keyRelease();

                    return ;
                }else{
                    return ;
                }
            }
        }else {
            return ;
        }


        Timer14_Run (1);
        
        Beep.BeepOnce();
        return ;
    }
}

void DualMode_KeyScon()
{
    uint32_t KeyTime_Count;

    if (KEY1 == KEY_ON || KEY2 == KEY_ON)  {
        delay_ms(30);

        if(KEY1 == KEY_ON) {   
            if(G_key2_flag == 1) {
                Valve2_OFF;
                G_key2_flag = 0 ;
            }else if(G_key1_flag == 0) { 
                G_key1_flag = 1 ; 
            }else { 
                Valve_OFF;
                G_key1_flag = 0;
            }
        }
        if(KEY2 == KEY_ON) {   
            if(G_key1_flag == 1) {
                Valve_OFF;
                G_key1_flag = 0 ;
            }else if( G_key2_flag == 0) {
                G_key2_flag = 1 ;
            }else {
                Valve2_OFF;
                G_key2_flag = 0 ;
            }
        }
		uint32 oNextTick = 0;
        SetDueTickMS(&oNextTick, 200);
        while (KEY1 == KEY_ON || KEY2 == KEY_ON){
            if(SysTickAfter(oNextTick)){
                Valve2_OFF;
                Valve_OFF;
				KeyTime_Count = 0;
            }
        }
        Beep.BeepOnce();
    }
}

void DualMode_OutMode(uint8_t oOut)
{
    static uint16_t err;
    static uint32_t oCounted;
    static uint32_t oSec, oSecC;
    static uint8_t  Time_Base,oPosMult16,oMode,sele = 0;
    volatile static uint32_t *oTimeCount;
    volatile static uint32_t *oPulseCount,*oPulseCount2,*oPulseTimeOut;

    static uint8_t dualControlMode_s;   

    if(oOut == 1) {      
        dualControlMode_s = PosParam.DualControlMode_1;
    }else if(oOut == 2) {
        dualControlMode_s = PosParam.DualControlMode_2;
    }
    // ???? ????
    switch (dualControlMode_s) {     
    case 0x10:       //????  1?
        Time_Base = 50;
        oCounted = Time_Base;
        oTimeCount = &Time13_Count;
        oPosMult16 = 1;
        oMode = 1;
        break;
    case 0x20:      //????  16/1??
        if(PosParam.DualControlMode == 0x6A && oOut == 2) {  
            oPulseCount = &G_PulseCount12;
            oPulseCount2 = &G_PulseCount12_1;
            oPulseTimeOut = &PulseTimeOut12;
        }else {
            oPulseCount = &G_PulseCount;
            oPulseCount2 = &G_PulseCount2;
            oPulseTimeOut = &PulseTimeOut;
        }
        oPosMult16 = 16;
        if(oOut == 1) {      
            oCounted = (uint32_t)PosParam.Out1Pulse * oPosMult16;
        }else if(oOut == 2) {
            oCounted = (uint32_t)PosParam.Out2Pulse * oPosMult16;
        }
        oMode = 2;
        break;
    case 0x30:     //????  1/16?
        Time_Base = 1;
        oCounted = Time_Base;
        oTimeCount = &Time14_Count;
        oPosMult16 = 1;
        oMode = 1;
        break;
    case 0x60:      //????  1??
        if(PosParam.DualControlMode == 0x6A && oOut == 2) {   
            oPulseCount = &G_PulseCount12;
            oPulseCount2 = &G_PulseCount12_1;
            oPulseTimeOut = &PulseTimeOut12;
        }else{
            oPulseCount = &G_PulseCount;
            oPulseCount2 = &G_PulseCount2;
            oPulseTimeOut = &PulseTimeOut;
        }
        oPosMult16 = 1;
        if(oOut == 1) {      
            oCounted = (uint32_t)PosParam.Out1Pulse * oPosMult16;
        }else if(oOut == 2) {
            oCounted = (uint32_t)PosParam.Out2Pulse * oPosMult16;
        }
        oMode = 2;
        break;
    default:
        break;
    }

    oSec = 0;
    if(oOut == 1) {      
        oSecC = PosParam.Out1Pulse * oPosMult16;
        err = Reader.PrepaySmall (PosParam.Out1Fee, true);
    }else if(oOut == 2) {
        oSecC = PosParam.Out2Pulse * oPosMult16;
        err = Reader.PrepaySmall (PosParam.Out2Fee, true);
    }
    if (err != nil) {
        if(oOut == 1)  {
            Valve_OFF;
        }else if(oOut == 2) {   
            Valve2_OFF;
        }
        disp.Balance(Reader.Purse.Balance);
        Beep.BeepGap(3);
        CheckCardOn();
        return ;
    }

    disp.Balance(Reader.Purse.Balance);
    disp.OneNum(1, 0, '-');
    SetTime13_Counter(on);
    SetTime14_Counter(on);
    SetPulseCounter(on); 
    SetPulseCounter_12(on); 
    if (oOut == 1){
        Valve_ON;   Valve2_OFF; 
    }else if (oOut == 2){
        Valve_OFF;   Valve2_ON; 
    }
    
    //CPU_M1_While_CardOn();
    while (Reader.ReadMoney() == nil) {
        err = DoDayLimit();
        if(err != nil) {   
            return;
        } 
        DualMode_KeyScon();

        if(G_key1_flag == 1 || G_key2_flag == 1) {
            G_key1_flag = 0;
            G_key2_flag = 0;
            
            disp.Clear();
            disp.Balance(Reader.Purse.Balance);
            Valve_OFF;
            Valve2_OFF;
            while (KEY1 == KEY_ON || KEY2 == KEY_ON);
            break;
        }
        if(oMode == 1) {   
            disp.OneNum(7, 0, '-');  

            if (*oTimeCount < oCounted) {
                if (Time13_Count2 >= 66) {   
                    Time13_Count2 = 0;
                    if (sele >= 5) {   
                        disp.OneNum(8, 2, 0x20); 
                        sele = 0; 
                    }else{
                        disp.OneNum(8, 2, 0x01 << sele); 
                        sele++;
                    }
                }
                Timer13_Run (1);
                Timer14_Run (1);
                continue;
            }

            disp.OneNum(7, 1, '-');
            
            oCounted = oCounted + Time_Base;//?????????
            oSec++;
            if (oSec < oSecC) {
                continue;  
            }

            if(oOut == 1){
                oSecC = PosParam.Out1Pulse * oPosMult16;  
            }else if(oOut == 2){   
                oSecC = PosParam.Out2Pulse * oPosMult16;  
            }
            oSec = 0;
        }else if(oMode == 2) {   
            disp.OneNum(7, 0, '_');  
            if (PosParam.StopSec) {
                if (Time14_Count > PosParam.StopSec) {       //????+????????????
                    if (*oPulseTimeOut < 3) {   
                        Valve_OFF;
                        Valve2_OFF;
                        SetTime13_Counter(off);
                        SetTime14_Counter(off);
                        SetPulseCounter(off);
                        SetPulseCounter_12(off); 
                        while(While_CardOn() == nil){
                            disp.TimeOut(); 
                        }
                        break;
                    }else {   
                        *oPulseTimeOut = 0;
                        Time14_Count = 0;
                    }
                }
            }
            if (*oPulseCount2 >= 4 ) {   
                *oPulseCount2 = 0;
                if (sele >= 5) {   
                    disp.OneNum(8, 2, 0x20); 
                    sele = 0; 
                }else{
                    disp.OneNum(8, 2, 0x01 << sele); 
                    sele++;
                }
            }
            if (*oPulseCount < oCounted){   
                continue; 
            }

            if(oOut == 1){
                oCounted = oCounted + (uint32_t)PosParam.Out1Pulse * oPosMult16;       //??????????
            }else if(oOut == 2){   
                oCounted = oCounted + (uint32_t)PosParam.Out2Pulse * oPosMult16;  
            }

            if (oCounted >= 0xFFFFF00F)   //??????
            {   oCounted = 0; }
        }

        if(oOut == 1){   
            err = Reader.PrepaySmall(PosParam.Out1Fee, true);      //???
        }else if(oOut == 2){
            err = Reader.PrepaySmall(PosParam.Out2Fee, true);       //???
        }
        if ( err != nil ) {
            if(oOut == 1) {
                Valve_OFF;
            }else if(oOut == 2) {
                Valve2_OFF;
            }
            disp.Balance(Reader.Purse.Balance);
            Beep.BeepGap(3);
            CheckCardOn();
            break;
        }
        
        disp.Balance(Reader.Purse.Balance );
        //Reader.ReadMoney();
    }
    Valve_OFF;
    Valve2_OFF;
    SetTime13_Counter(off);
    SetTime14_Counter(off);
    SetPulseCounter(off);
    SetPulseCounter_12(off);
    SaveAmountFun();
}

void DualMode_Run()
{
    uint16_t Cadron;
    CPU_M1_While_CardOn();

    while (While_CardOn() == nil){
        disp.Balance(Reader.Purse.Balance);  //????
        DualMode_KeyScon();
        if(G_key1_flag == 1 && G_key2_flag == 0)  {
            G_key1_flag = 0;
            DualMode_OutMode(OUT_1);
        }
        if(G_key1_flag == 0 && G_key2_flag == 1)  {
            G_key2_flag = 0;
            DualMode_OutMode(OUT_2);
        }

        Valve_OFF;
        Valve2_OFF;
        SetPulseCounter(off);
        SetTime13_Counter(off);
        SetTime14_Counter(off);
    }
}
#endif



void DoMainTask()
{
    static uint16_t err, err1;
    static uint32_t oNextTick1;  

    err = Reader.Find(G_CardSN); // 寻卡
    if (err != nil)
     {
        if (err != 1){          
            G_Error_Count++;
            if (G_Error_Count >= 3) {
                G_Error_Count = 0;
                disp.ErrorCode(err);        
            #ifdef DUAL_MODE
                if(G_DualRatModeShow == 1) {
                    return; 
                }
            #endif
                CheckCardOn();         
            }
        }
        GCardOn = false;
        GCPUCard = false;
        
        if(SysTickAfter(oNextTick1)){

            Return_PcdReset();
            SetDueTickMS(&oNextTick1, 5000);
        }
        return;
    }

    GCardOn = true; //标记卡放上
#ifdef SEGLCD
    disp.Backlight(on);
#endif
 
    err = Reader.ReadNum(G_CardSN);          // 获取卡号
   
    if (err != nil) 
    {
        G_Error_Count++;
        if (G_Error_Count >= 3) {
            G_Error_Count = 0;
            disp.ErrorCode(err);
        #ifdef DUAL_MODE
            if(G_DualRatModeShow == 1){   
                return; 
            }
        #endif
            CheckCardOn();  //{ ????????? }
        }
        Return_PcdReset();
        return;
    }
    // ?????????
    if (GOperOn)
    {
        OperCardTask();//???????????????????????
        return;
    }
    //??CPU???
    if (PosParam.EnableUserCard == 0x01 && oType == 0x0400) 
    { 
        disp.ErrorCode(311);
    #ifdef DUAL_MODE
        if(G_DualRatModeShow == 1){   
            return; 
        }
    #endif
        CheckCardOn();
        return; 
    }
    // ??M1???
    if ((PosParam.EnableUserCard == 0x02) && ((oType == 0x0800) || (oType == 0x0200)))
     { 
        disp.ErrorCode(312);
    #ifdef DUAL_MODE
        if(G_DualRatModeShow == 1){
           return;
        }
    #endif
        CheckCardOn();
        return;
    }
    //??????????????CPU??M1?????

    // ???????
    if (Reader.Purse.AuthCode != PosParam.AuthCode){
        disp.AuthCode (Reader.Purse.AuthCode);
        Beep.BeepGap(3);
    #ifdef DUAL_MODE
        if(G_DualRatModeShow == 1){   
            return; 
        }
    #endif
        CheckCardOn();
        return;
    }
    // ????
    err = Reader.ReadMoney();
    if (err != nil){
        G_Error_Count++;
        if (G_Error_Count >= 2) {
            G_Error_Count = 0;
            disp.ErrorCode(err);
        #ifdef DUAL_MODE
            if(G_DualRatModeShow == 1){   
                return; 
            }
        #endif
            CheckCardOn();  //{ ????????? }
        }
        Return_PcdReset();
        return;
    }
#ifdef DUAL_MODE
    //?????? ????????
    if( PosParam.Dual_RationMode == 1){
        DualRatMode_Run();
        return;
    }

    if(PosParam.DualMode == 0x5A){
        disp.Clear();
        disp.Balance(Reader.Purse.Balance);  //????
        //???????
        if ((PosParam.MaxBalance_Flag == 1) && (Reader.Purse.Balance > PosParam.MaxBalance)) {  
            //???? ??????
            Beep.BeepGap(1);
            disp.ErrorCode(406);//?????????

            CheckCardOn();
            return;
        }
        //?????????
        if ((Reader.Purse.Balance < PosParam.RetenMoney) && PosParam.RetenMoneyFlag) {   
            //???? ?????
            Beep.BeepGap(1);
            disp.ErrorCode(407);//?????????

            CheckCardOn();
            return;
        }
        DualMode_Run();
        return;
    }
    if(PosParam.PulseOutMode == 0x5A){
        disp.Clear();
        disp.Balance(Reader.Purse.Balance);  //????
        err = Reader.PrepaySmall (PosParam.OutFee, true);//???
        if (err != nil){   
            Valve_OFF;//?????
            Beep.BeepGap(3);
            CPU_M1_While_CardOn();
            while(While_CardOn() == nil);
            return ;
        }
        Valve_ON; 
        delay_ms(40);
        Valve_OFF; 
        delay_ms(60);
        Beep.BeepOnce();

        CPU_M1_While_CardOn();
        while(While_CardOn() == nil);
        return ;
    }
#endif
    //?????? ??????
    DoFreeUseMode();
    err = DoDayLimit();
    if(err != nil) {   
        //Return_PcdReset();  
        return;
    } 

    disp.Clear();
    disp.Balance(Reader.Purse.Balance);  //????
    //???????
    if ((PosParam.MaxBalance_Flag == 1) && (Reader.Purse.Balance > PosParam.MaxBalance)) {
        //???? ??????
        disp.ErrorCode(406);//?????????
        CheckCardOn ();
        return;
    }
    //?????????
    if ((Reader.Purse.Balance < PosParam.RetenMoney) && PosParam.RetenMoneyFlag){   
        //???? ?????
        disp.ErrorCode(407);//?????????
        CheckCardOn();
        return;
    }
    //????
    DelayCutProcess();	
    // ????????
    if (Reader.Purse.Balance > 0){
        delay_ms(120);
        if (PosParam.RationMode == 1) {  //????
            DoUsingOnF7(); 
        }else{
            //????
            if ((PosParam.MeasureMode == 0x20) || (PosParam.MeasureMode == 0x60) || (PosParam.MeasureMode == 0x00)){    
                //????
                if (PosParam.SpecDeduMode == 1){
                    err1 = SpecDeduModePlus();
                    if (err1 == 2){
                        //Return_PcdReset();
                        return;
                    }
                }
                DoUsingOnPulse();   
            }
            //????
            if ((PosParam.MeasureMode == 0x10) || (PosParam.MeasureMode == 0x30)){   
                //????
                if (PosParam.SpecDeduMode == 1){
                    err1 = SpecDeduModeTime(); 
                    if(err1 == 2) {   
                        //Return_PcdReset();
                        return;
                    }
                }
                DoUsingOnTime();
            }
        }
    }
    else{
    #ifdef SEGLCD
        disp.WriteMulDig(6, 2, 0);
        disp.LcdData (11, 0x08); // ?? + ?
        disp.LcdData (17, 0x02); //? ??
    #endif 
        Beep.BeepGap(3);
        CPU_M1_While_CardOn();
        while(While_CardOn()==nil);
    }
    delay_ms(60);
    //Return_PcdReset();
}

